小编典典

fork 和 exec 的区别

all

fork 和 exec 的区别


阅读 167

收藏
2022-06-04

共1个答案

小编典典

使用forkexec体现了 UNIX 的精神,因为它提供了一种非常简单的方式来启动新进程。

fork调用基本上复制了当前进程,几乎在所有方面都相同。并非所有内容都被复制(例如,某些实现中的资源限制),但其想法是创建尽可能接近的副本。

新进程(子进程)获得不同的进程 ID(PID),并将旧进程(父进程)的 PID 作为其父进程 PID(PPID)。因为这两个进程现在运行的代码完全相同,所以它们可以通过返回代码来判断哪个是哪个fork- 子进程获取 0,父进程获取子进程的 PID。当然,假设fork调用有效,这就是全部 - 如果没有,则不会创建子节点并且父节点会收到错误代码。

exec调用是一种基本上用新程序替换整个当前进程的方法。它将程序加载到当前进程空间并从入口点运行它。

因此,fork经常exec按顺序使用,以使新程序作为当前进程的子进程运行。当你尝试运行一个程序时,shell 通常会这样做find——shell fork,然后子进程将find程序加载到内存中,设置所有命令行参数、标准 I/O 等等。

但它们不需要一起使用。例如,如果程序同时包含父代码和子代码(您需要小心您所做的事情,每个实现都可能有限制),那么程序fork本身没有ing是完全可以接受的。exec这在守护进程中被大量使用(现在仍然如此),这些守护进程只是侦听 TCP 端口和fork自身的副本,以在父进程返回侦听时处理特定请求。

同样,知道自己已经完成并且只想运行另一个程序的程序不需要forkexec然后wait为孩子。他们可以直接将孩子加载到他们的进程空间中。

一些 UNIX 实现有一个优化fork,它使用他们所谓的写时复制。这是一种延迟复制进程空间的技巧,fork直到程序尝试更改该空间中的某些内容。这对于那些只使用fork而不是exec因为它们不必复制整个进程空间的程序很有用。

如果exec 称为跟随fork(这是最常发生的情况),则会导致写入进程空间,然后将其复制给子进程。

请注意,有一个完整的exec调用系列(execlexecleexecve),但exec在上下文中,这里指的是它们中的任何一个。

下图说明了使用 shell 使用命令列出目录的典型fork/exec操作:bash``ls

+--------+
| pid=7  |
| ppid=4 |
| bash   |
+--------+
    |
    | calls fork
    V
+--------+             +--------+
| pid=7  |    forks    | pid=22 |
| ppid=4 | ----------> | ppid=7 |
| bash   |             | bash   |
+--------+             +--------+
    |                      |
    | waits for pid 22     | calls exec to run ls
    |                      V
    |                  +--------+
    |                  | pid=22 |
    |                  | ppid=7 |
    |                  | ls     |
    V                  +--------+
+--------+                 |
| pid=7  |                 | exits
| ppid=4 | <---------------+
| bash   |
+--------+
    |
    | continues
    V
2022-06-04